/**
 * 此分程序主要是计算优先关系表
 * 优先分析表是算符优先文法的关键，因此应该慎重对待
 * 如何建表，建什么类型的表，表的使用是不是方便都是我们要考虑的情况
 */

/**
 * 创建并填写优先级表
 * 对每个产生式遍历，求出四种关系1.=, 2.<, 3.>, 4.没有关系
 *      ↑↑↑↑↑↑
 */
const createPriorityTable = () => {
    const tableCoordinate = ['+', '-', '*', '/', '(', ')', 'v', 'c', '=', '?', '#', '\0'];
    const renderPriorityTable = twoDimensionalArrays(12, 12, '\0');

    // 初始化行列，填充行列坐标元素
    for (let r = 1; r < 12; r++) {
        PriorityTable[0][r] = tableCoordinate[r - 1];
        PriorityTable[r][0] = tableCoordinate[r - 1];

        renderPriorityTable[0][r] = tableCoordinate[r - 1];
        renderPriorityTable[r][0] = tableCoordinate[r - 1];
    }

    console.log('---renderPriorityTable: ', renderPriorityTable);

    let table = ``;
    for (let i = 0; i < renderPriorityTable.length; i++) {
        let rowTag = `<div class="priority_table_row">`;
        for (let j = 0; j < renderPriorityTable[i].length; j++) {
            rowTag += `<div>${renderPriorityTable[i][j]}</div>`;
        }
        const rowCloseTag = `</div>`;
        rowTag += rowCloseTag;

        table += rowTag;
    }

    document.getElementById('PriorityTable').innerHTML = table;
};

const fillPriorityTable = () => {
    let j = 0;
    let L = 0;

    // 表的元素坐标
    let tbl_row = 0;
    let tbl_col = 0;

    let C = [];

    // 扫描产生式的右部，如果发现终结符且该终结符周围有其他字符
    // 1.若该其他字符为终结符，则这两者关系为相等
    // 2.若该其他字符为非终结符，则根据非终结符的firstVT,LastVt填表

    /**
     * 概念详细描述：
     * a = b: 当前仅当文法G中含有形如 P=>...ab... 或 P=>...aQb... 的产生式
     * a < b: 当且仅当G中含有形如 P=>...aR...，且 R=>b... 或 R=>Qb...
     * a > b: 当且仅当G中含有形如 P=>...Rb...，且 R=>...a 或 R=>...aQ
     */
    for (let p = 0; INPUT[p][0] !== '\n'; p++) {
        j = 0;
        for (let i = 4; i < 20; i++) {
            if (INPUT[p][i] === '|' || INPUT[p][i] === '\n') {
                L = j; // j 即是 产生式右部的长度
                j = 0;

                // 产生式右部的长度 大于 1，判断两个终结符的优先关系，填表逻辑就是 一个终结符对应：tbl_col，另一个对应：tbl_row
                if (L > 1) {
                    // 若为终结符因至少有两个,若出现两个终结符则C[0]'=='C[1]||C[2]，注意这是此文法的情况
                    // 则需要填表，查表找到C[0]的行数，C[1],C[2]的列数进行填表

                    // 形如：ab 或者 aQb
                    if (
                        (IsVT(C[0]) && IsVT(C[1])) ||
                        (L === 3 && IsVT(C[0]) && IsVT(C[2]) && FL_map(C[1]) !== -1)
                    ) {
                        tbl_row = SearchTbl(C[0]); // 记录行数
                        // 形如：ab
                        if (IsVT(C[1])) {
                            tbl_col = SearchTbl(C[1]);
                        }
                        // 形如：aQb
                        if (IsVT(C[2]) && L === 3) {
                            // 列数 (E)
                            tbl_col = SearchTbl(C[2]);
                        }
                        PriorityTable[tbl_row][tbl_col] = '='; // 填表

                        // case: a < b   [eg: v=E => = <· FIRSTVT(E)]
                        if (L === 3 && IsVT(C[0]) && IsVT(C[1]) && FL_map(C[2]) !== -1) {
                            let t_idx = 0; // firstVT中的终结符索引
                            tbl_row = SearchTbl(C[1]);

                            // FL_map() 求符号对应的产生式
                            // 读取FIRSTVT集中的所有终结符
                            while (FIRSTVT[FL_map(C[2])][t_idx] !== '\0') {
                                const t = FIRSTVT[FL_map(C[2])][t_idx]; // 读取终结符
                                tbl_col = SearchTbl(t); // 将上述结果再次转换
                                PriorityTable[tbl_row][tbl_col] = '<'; // 填写关系：tbl_row元素 < tbl_col元素
                                // PriorityTable[tbl_col][tbl_row] = '>';
                                t_idx++; // 向后扫描FIRSTVT集
                            }
                            t_idx = 0; // 清零
                        }

                        // 形如：aQb [eg: (E)]
                        if (L === 3 && IsVT(C[0]) && IsVT(C[2]) && FL_map(C[1]) !== -1) {
                            // 首先填写<关系
                            let temp_row;
                            let temp_col;
                            let t_idx = 0;
                            tbl_row = SearchTbl(C[0]);

                            // 扫描 aQ... 中 Q 的firstVT集
                            while (FIRSTVT[FL_map(C[1])][t_idx] !== '\0') {
                                // 填写小于关系 '(' <· firstVT(E)
                                temp_col = FIRSTVT[FL_map(C[1])][t_idx];
                                tbl_col = SearchTbl(temp_col);
                                PriorityTable[tbl_row][tbl_col] = '<';
                                t_idx++;
                            }
                            t_idx = 0;
                            tbl_col = SearchTbl(C[2]);
                            // 扫描 ...Qa 中 Q 的lastVT集
                            while (LASTVT[FL_map(C[1])][t_idx] !== '\0') {
                                // 填写大于关系 lastVT(E) ·> ')'
                                temp_row = LASTVT[FL_map(C[1])][t_idx];
                                tbl_row = SearchTbl(temp_row);
                                PriorityTable[tbl_row][tbl_col] = '>';
                                t_idx++;
                            }
                            t_idx = 0;
                        }
                    } else if (FL_map(C[0]) !== -1 && IsVT(C[1])) { // 形如 QaR
                        // C[0]肯定为非终结符lastVT(C[0])>C[1]
                        // 填写大于关系
                        let temp_row;
                        let temp_col;
                        let count = 0;
                        tbl_col = SearchTbl(C[1]);
                        while (LASTVT[FL_map(C[0])][count] !== '\0') {
                            temp_row = LASTVT[FL_map(C[0])][count];
                            tbl_row = SearchTbl(temp_row);
                            PriorityTable[tbl_row][tbl_col] = '>';
                            count++;
                        }
                        count = 0;
                        if (L === 3) {
                            // 在这种情况下C[2]必为非终结符，求C[2]的firstVT(),填写小于关系
                            // E+T,E-T,T*F,T/F等情况
                            tbl_row = SearchTbl(C[1]);
                            while (FIRSTVT[FL_map(C[2])][count] !== '\0') {
                                // 填写小于关系
                                temp_col = FIRSTVT[FL_map(C[2])][count];
                                tbl_col = SearchTbl(temp_col);
                                PriorityTable[tbl_row][tbl_col] = '<';
                                count++;
                            }
                            count = 0;
                        }
                    }
                }
            } else if (INPUT[p][i] !== '|' || INPUT[p][i] !== '\n') {
                C[j] = INPUT[p][i]; // 从 j = 0 开始
                j++; // 移进
            }

            // 当前产生式扫描结束
            if (INPUT[p][i] === '\n') {
                break;
            }
        }
    }

    // 补上#的关系
    for (let m1 = 1; m1 < 11; m1++) {
        PriorityTable[SearchTbl('#')][m1] = '<'; // 这个容易理解，补行
    }
    for (let m2 = 1; m2 < 11; m2++) {
        PriorityTable[m2][SearchTbl('#')] = '>'; // 补列
    }
    PriorityTable[SearchTbl('#')][SearchTbl('#')] = '=';
};

const displayPriorityTab = () => {
    let table = `PriorityTable: \n`;
    for (let i = 0; i < 12; i++) {
        let rowTag = `<div class="priority_table_row">`;
        for (let j = 0; j < 12; j++) {
            rowTag += `<div>${PriorityTable[i][j]}</div>`;
        }
        const rowCloseTag = `</div>`;
        rowTag += rowCloseTag;

        table += rowTag;
    }

    document.getElementById('PriorityTable').innerHTML = table;
}
